﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DiscoveryLogic.UI.Layouts.Controls;
using DiscoveryLogic.DataServices.DataSources;
using System.Windows.Markup;
using System.Threading;
using DiscoveryLogic.UI.Layouts.Converters;


namespace DiscoveryLogic.UI.Layouts.Controls
{
    public partial class LineGraph : UserControl, IGraphControl
    {
        private Account model;

        // Variables for Mouse Events
        bool isMouseOver = false;
        bool isMouseDown = false;
        double originMouseX;
        double originMouseY;
        double currentMouseX;
        double currentMouseY;
        
        double delta;
        TextBlock completed;
        double initialOffset = 34.344;

        // Variable for savings label
        DateTime initialCompletionDate = DateTime.Today;

        public Account Model
        {
            get { return model; }
            set
            {
                model = value;
                DrawAnumMarks((MortgageAccount)model);
                InitializeSlider();
                UpdateSavings();
            }
        }
        public LineGraph()
        {
            InitializeComponent();

            BalanceLegend.Text = string.Format(this.Resources["Res_BalanceLegend"].ToString(), Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol);


            model = null;
            
            
            completed = (TextBlock)LineGraphCanvas.FindName("Complete");
            

            LineGraphLine lineGraphLine = new LineGraphLine();
            lineGraphLine.SetValue(Canvas.NameProperty, "LineGraph");
            ((Canvas)LineGraphCanvas.FindName("GraphLineCanvas")).Children.Add(lineGraphLine);
        }

        public LineGraph(Account model)
            : this()
        {
            this.model = model;
            DrawAnumMarks((MortgageAccount)model);
            
        }

        private void InitializeSlider()
        {
            double sliderLeft = (double)SliderCanvas.GetValue(Canvas.LeftProperty);
            Path axis = (Path)LineGraphCanvas.FindName("Axis");
            DateTime estimatedCompletionDate = ((MortgageAccount)model).ProjectedPaymentCompleteDate;//((MortgageAccount)model).PaymentSchedule.StartDate.AddMonths(((MortgageAccount)model).PaymentSchedule.TotalPayments);
            double newPos = DateToPosition(estimatedCompletionDate, axis.Width, ((MortgageAccount)model).PaymentSchedule.TotalPayments, ((MortgageAccount)model).PaymentSchedule.StartDate);
            SetSliderAbsolute(newPos + initialOffset);
            
    
        }

        private void UpdateSavings()
        {
            Path axis = (Path)LineGraphCanvas.FindName("Axis");
            
            double sliderLeft = (double)SliderCanvas.GetValue(Canvas.LeftProperty);

            // Start estimated completion date
            DateTime estimatedCompletionDate = initialCompletionDate;

            // Completion date the slider is on
            DateTime sliderCompletionDate = PositionToDate(sliderLeft, 
                                                           axis.Width, 
                                                           ((MortgageAccount)model).PaymentSchedule.TotalPayments,
                                                           ((MortgageAccount)model).PaymentSchedule.StartDate);

            // Amount of interest per payment
            double interestPerPayment = ((MortgageAccount)model).NextPaymentInterest;

            // Money saved on interest
            double savings = 0;

            if (sliderCompletionDate < estimatedCompletionDate)
            {
                TimeSpan interval = (estimatedCompletionDate - sliderCompletionDate);
                savings = Math.Round((interval.Days / 365.0) * 12.0 * interestPerPayment/2);
            }
            else
            {
                // Savings are zero
            }

            TextBlock savingsText = LineGraphCanvas.FindName("SavingsAmount") as TextBlock;
            savingsText.Text = savings.ToCurrency();
        }

        private void DrawAnumMarks(MortgageAccount model)
        {
            if (model != null)
            {
                Path axis = (Path)LineGraphCanvas.FindName("Axis");
                double leftEdge = (double)axis.GetValue(Canvas.LeftProperty);
                double width = (double)axis.GetValue(Canvas.WidthProperty);
                int periods = model.PaymentSchedule.TotalPayments;
                int yearSpacing = 5;
                double ticks = periods / 12.0 / Convert.ToDouble(yearSpacing);
                double increment = width / (double)ticks;

                double tickCanvasLeft;
                DateTime startDate = model.PaymentSchedule.StartDate;
                TextBlock newTextBlock;
                for (int i = 0; i <= ticks; i++)
                {
                    tickCanvasLeft = initialOffset + i * increment;
                    newTextBlock = new TextBlock();
                    newTextBlock.Height = 23.873;
                    newTextBlock.FontSize = 8;
                    newTextBlock.TextWrapping = TextWrapping.Wrap;
                    newTextBlock.Width = 23.322;
                    newTextBlock.SetValue(Canvas.TopProperty, 131.627);
                    newTextBlock.SetValue(Canvas.LeftProperty, tickCanvasLeft);
                    newTextBlock.Text = String.Format("{0:MMMM} {1:yyyy}",(startDate.AddYears (i*yearSpacing)), (startDate.AddYears (i*yearSpacing))) ;
                    LineGraphCanvas.Children.Add(newTextBlock);
                }
            }


                //<TextBlock Height="23.873" FontSize="8" Text="June 2001" TextWrapping="Wrap" Width="23.322" Canvas.Left="34.344" Canvas.Top="131.627" FontFamily="Trebuchet MS"/>
                
        }


        protected void CanvasMouseEnter(object sender, EventArgs args)
        {
            ((Canvas)sender).Cursor = Cursors.Hand;
        }

        protected void CanvasMouseLeave(object sender, EventArgs args)
        {
            ((Canvas)sender).Cursor  = Cursors.Arrow; 
        }



        public void CanvasMouseLeftButtonDown(object sender, EventArgs args)
        {
            isMouseDown = true;

            Canvas can = (Canvas)sender;

            originMouseX = ((MouseEventArgs)args).GetPosition(null).X;

            originMouseY = ((MouseEventArgs)args).GetPosition(null).Y;

            can.CaptureMouse();
        }

        public void CanvasMouseLeftButtonUp(object sender, EventArgs args)
        {
            Canvas can = (Canvas)sender;
            can.ReleaseMouseCapture();
            isMouseDown = false;
        }

        public void CanvasMouseMove(object sender, MouseEventArgs args)
        {

            // If mouse button is still in down position
            if (isMouseDown)
            {
                // Retrieve current mouse position
                currentMouseX = args.GetPosition(null).X;
                currentMouseY = args.GetPosition(null).Y;

                double deltaX = (currentMouseX - originMouseX);

                // Set slider thumb position
                SetSlider(deltaX);

                // Raise event
                OnSliderChanged(new EventArgs());
            } 
        }

        private DateTime PositionToDate(double pos, double width, int numberOfPayments, DateTime startDate)
        {
            double offset = (numberOfPayments * (pos - initialOffset)) / width;
            int increment = Convert.ToInt32(offset);
            return startDate.AddMonths(increment);
        }

        private double DateToPosition(DateTime date, double width, int numberOfPayments, DateTime startDate)
        {
            System.TimeSpan termPassed = date - startDate;
            System.TimeSpan term = startDate.AddMonths(numberOfPayments) - startDate;
            double percentOfTerm = ((double)termPassed.Days) / ((double)term.Days);
            return width * percentOfTerm;
        }

        
        #region IGraphControl Members
        public double GetLastSliderChange() {
            return delta;
        }

        public void SetSlider(double delta)
        {            
            

            // Find slider thumb and its dimensions
            
            double sliderThumbWidth = (double)SliderThumb.GetValue(Ellipse.WidthProperty);

            // Find slider bar and its dimensions            
            double sliderBarMin = (double)Axis.GetValue(Canvas.LeftProperty)
                                - sliderThumbWidth / 2;
            double sliderBarMax = (double)Axis.GetValue(Canvas.LeftProperty)
                                + Axis.Width
                                - sliderThumbWidth / 2;

            double sliderMinAllowable = sliderBarMin + 143;

            double newValue = (double)SliderCanvas.GetValue(Canvas.LeftProperty)
                               + delta;

            // Ensure that slider thumb doesn`t go beyond min or max
            if (newValue > sliderBarMax)
            {
                newValue = sliderBarMax;
                delta = sliderBarMax
                        - (double)SliderCanvas.GetValue(Canvas.LeftProperty);
            }

            if (newValue < sliderMinAllowable)
            {
                newValue = sliderMinAllowable;
                delta = sliderMinAllowable
                        - (double)SliderCanvas.GetValue(Canvas.LeftProperty);
            }

            this.delta = delta ;
              
            Controls.LineGraphLine line = (Controls.LineGraphLine)LineGraphCanvas.FindName("LineGraph");

            double sliderLeft = (double)SliderCanvas.GetValue(Canvas.LeftProperty);

            bool trackValid = false;
            if (line != null)
            {
                trackValid = line.AlterTrack(delta);
            }

            // Reset the location of the object
            if (trackValid)
            {
                // Set Value
                SliderCanvas.SetValue(Canvas.LeftProperty, newValue);

                // Update the beginning position of the mouse
                originMouseX = currentMouseX;
                originMouseY = currentMouseY;

                DateTime completedDate = PositionToDate(sliderLeft + delta, Axis.Width, ((MortgageAccount)model).PaymentSchedule.TotalPayments, ((MortgageAccount)model).PaymentSchedule.StartDate);
                Run completedText = (Run)SliderCanvas.FindName("CompletedDate");
                completedText.Text = String.Format("{0:MMMM} {0:yyyy}", completedDate);

                // Update amount on savings label
                UpdateSavings();
            }   
        }

        public void SetSliderAbsolute(double pos)
        {
            
            Controls.LineGraphLine line = (Controls.LineGraphLine)LineGraphCanvas.FindName("LineGraph");

            double sliderLeft = (double)SliderCanvas.GetValue(Canvas.LeftProperty);

            bool trackValid = false;
            if (line != null)
            {
                trackValid = line.SetTrack(pos - initialOffset - (SliderThumb.Height / 2), true);
            }

            // Reset the location of the object
            if (trackValid)
            {
                SliderCanvas.SetValue(
                    Canvas.LeftProperty,
                    pos
                    );

                // Update the beginning position of the mouse
                originMouseX = currentMouseX;
                originMouseY = currentMouseY;

                Path axis = (Path)LineGraphCanvas.FindName("Axis");
                DateTime completedDate = PositionToDate(pos, axis.Width, ((MortgageAccount)model).PaymentSchedule.TotalPayments, ((MortgageAccount)model).PaymentSchedule.StartDate);
                Run completedText = (Run)SliderCanvas.FindName("CompletedDate");
                completedText.Text = String.Format("{0:MMMM} {0:yyyy}", completedDate);

                // Update initial completion date to the current
                // date at slider
                initialCompletionDate = completedDate;
                // Update amount on savings label
                UpdateSavings();
            }
        }

        #endregion

        #region IGraphControl Members


            public event SliderChangedEventHandler SliderChanged;

            public void OnSliderChanged(EventArgs e)
            {
                if (SliderChanged != null)
                {
                    SliderChanged(this, e);
                }
            }

            /// <summary>
            /// Gets distance from slider thumb to min of slider bar
            /// </summary>
            /// <returns></returns>
            public double GetCurrentPosition()
            {                
                double sliderThumbWidth = (double)SliderThumb.GetValue(Ellipse.WidthProperty);
                
                double sliderBarMin = (double)Axis.GetValue(Canvas.LeftProperty)
                                    - sliderThumbWidth / 2;
                
                double sliderMinAllowable = sliderBarMin + 143;

                return Math.Abs(sliderMinAllowable - 
                                (double)SliderCanvas.GetValue(Canvas.LeftProperty) + (SliderCanvas.Width / 2));
            }

            public double GetSliderLength()
            {

                // Find slider thumb and its dimensions                
                double sliderThumbWidth = (double)SliderThumb.GetValue(Ellipse.WidthProperty);

                // Find slider bar and its dimensions                
                double sliderBarMin = (double)Axis.GetValue(Canvas.LeftProperty)
                                    - sliderThumbWidth / 2;
                double sliderBarMax = (double)Axis.GetValue(Canvas.LeftProperty)
                                    + Axis.Width
                                    - sliderThumbWidth / 2;

                double sliderMinAllowable = sliderBarMin + 143;

                return (sliderBarMax - sliderMinAllowable);
            }

            /// <summary>
            /// Set slider position based on a percentage.
            /// Also sets the vertical start notch position on the axis
            /// </summary>
            /// <param name="percent"></param>
            public void SetSliderPercent(double percent)
            {
                double sliderThumbWidth = (double)SliderThumb.GetValue(Ellipse.WidthProperty);
                
                double sliderBarMax = (double)Axis.GetValue(Canvas.LeftProperty)
                    + Axis.Width
                    - sliderThumbWidth / 2;

                double offset = percent * this.GetSliderLength();
                double desiredPosition = sliderBarMax - offset;

                this.SetSlider(desiredPosition 
                               - ((double)SliderCanvas.GetValue(Canvas.LeftProperty) + sliderThumbWidth +.8));

                // Set start notch as well
                Path startNotch = LineGraphCanvas.FindName("StartNotch") as Path;
                startNotch.SetValue(Canvas.LeftProperty, desiredPosition - sliderThumbWidth/2 - .8);

                // Update initial completion date to the current
                // date at slider
                DateTime completedDate = PositionToDate(desiredPosition - sliderThumbWidth - .8,
                                                        Axis.Width, 
                                                        ((MortgageAccount)model).PaymentSchedule.TotalPayments, 
                                                        ((MortgageAccount)model).PaymentSchedule.StartDate);
                initialCompletionDate = completedDate;
                // Update amount on savings label
                UpdateSavings();
            }

        #endregion

    }
}
